import MonacoEditor, { EditorProps, loader } from '@monaco-editor/react'
import * as monaco from 'monaco-editor'
import { editor } from 'monaco-editor'
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import React from 'react'

self.MonacoEnvironment = {
    getWorker(_, label) {
        if (label === 'json') {
            return new jsonWorker()
        }
        if (label === 'typescript' || label === 'javascript') {
            return new tsWorker()
        }
        return new editorWorker()
    },
}

loader.config({ monaco })

loader.init().then(() => {
    console.log('Monaco editor initialized')
})

interface IEditorProps extends EditorProps {
    // 额外的库
    exteraLibs?: string
    // options
    options?: editor.IStandaloneEditorConstructionOptions
    // ref
    editorRef?: React.RefObject<IEditorRef | null>
    // 失焦事件
    onBlur?: () => void
}

export interface IEditorRef {
    // 编辑器实例
    editor: editor.IStandaloneCodeEditor | null
    // 获取内容
    getValue: () => string
    // 设置内容
    setValue: (value: string) => void
    // 格式化文档
    format: () => Promise<void>
}

const Editor: React.FC<IEditorProps> = ({
    onBlur,
    onMount,
    exteraLibs,
    options,
    editorRef: parentRef,
    ...props
}) => {
    const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)

    // 编辑器挂在完成后
    const handleEditorDidMount = (
        editor: editor.IStandaloneCodeEditor,
        monacoInstance: typeof monaco,
    ) => {
        editorRef.current = editor
        // 改一些配置
        editor.updateOptions({
            minimap: { enabled: false },
            // lineNumbers: 'off',
            fontSize: 16,
        })
        // 失焦事件
        editor.onDidBlurEditorWidget(() => {
            onBlur?.()
        })
        // 设置选项
        if (options) {
            editor.updateOptions(options)
        }
        // 添加自定义的类型定义
        if (exteraLibs) {
            // 添加额外的库
            monacoInstance.languages.typescript.javascriptDefaults.addExtraLib(
                exteraLibs,
            )
        }
        // 设置ref
        if (parentRef) {
            parentRef.current = {
                editor,
                getValue: () => editor.getValue(),
                setValue: (value: string) => editor.setValue(value),
                format: async () => {
                    await editor
                        .getAction('editor.action.formatDocument')
                        ?.run()
                },
            }
        }
        // 挂在完成后
        onMount?.(editor, monacoInstance)
    }

    return (
        <MonacoEditor
            height='500px'
            theme='light'
            language='json'
            {...props}
            className={`border border-solid border-gray-300 ${props.className}`}
            onMount={handleEditorDidMount}
        />
    )
}

export default Editor
